package com.neu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.neu.base.PageBean;
import com.neu.base.Result;
import com.neu.base.ServerSentEventsResult;
import com.neu.entity.DTO.InvitationDTO;
import com.neu.enums.ServerSentEventsEnum;
import com.neu.entity.*;
import com.neu.entity.DTO.NoticeDTO;
import com.neu.entity.security.LoginUser;
import com.neu.handler.ServerSentEventsManager;
import com.neu.mapper.NoticeMapper;
import com.neu.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class NoticeServiceImpl extends ServiceImpl<NoticeMapper, Notice> implements NoticeService {
    @Autowired
    TenantService tenantService;

    @Autowired
    UserService userService;

    @Autowired
    private NoticeUserService noticeUserService;

    @Autowired
    ProjectUserRoleService projectUserRoleService;
    @Autowired
    InvitationService invitationService;


    @Override
    public PageBean<NoticeDTO> pagelist(Integer pageNum, Integer pageSize) {
        Page<Notice> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Notice> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Notice::getDelFlag, "1");// 查询未删除的通知
        //直接查自己发出的通知以及自己收到的通知
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        queryWrapper.eq(Notice::getCreateId, loginUser.getUserId());
        List<NoticeUser> noticeUserList = noticeUserService.list(new LambdaQueryWrapper<NoticeUser>().eq(NoticeUser::getUserId, loginUser.getUserId()));
        if(!noticeUserList.isEmpty()){
            Set<String> noticeIds = noticeUserList.stream().map(NoticeUser::getNoticeId).collect(Collectors.toSet());
            queryWrapper.or().in(Notice::getNoticeId, noticeIds);
        }
        Page<Notice> noticePage = this.page(page, queryWrapper);
        List<Notice> records = noticePage.getRecords();
        if(records.isEmpty()){
            return new PageBean<>(noticePage.getCurrent(), noticePage.getSize(), noticePage.getTotal(), new ArrayList<>());
        }
        List<NoticeDTO> noticeDTOS = getNoticeDTOS(records);
        PageBean<NoticeDTO> pageBean = new PageBean<>(noticePage.getCurrent(), noticePage.getSize(), noticePage.getTotal(), noticeDTOS);
        return pageBean;
    }



    private List<NoticeDTO> getNoticeDTOS(List<Notice> records) {
        List<NoticeDTO> noticeDTOS = new ArrayList<>();
        for (Notice notice : records) {
            NoticeDTO noticeDTO = new NoticeDTO();
            BeanUtil.copyProperties(notice, noticeDTO);

            String tenantId = notice.getTenantId();
            noticeDTO.setTenantName(tenantService.getById(tenantId).getTenantName());


            String createBy = notice.getCreateId();
            noticeDTO.setPulishName(userService.getById(createBy).getUsername());

            String noticeId = notice.getNoticeId();
            List<NoticeUser> noticeUsers = noticeUserService.list(new LambdaQueryWrapper<NoticeUser>().eq(NoticeUser::getNoticeId, noticeId));
            if(noticeUsers.isEmpty()){
                noticeDTO.setUserList(new ArrayList<>());
                noticeDTOS.add(noticeDTO);
                continue;
            }
            Set<String> userIds = noticeUsers.stream().map(NoticeUser::getUserId).collect(Collectors.toSet());
            List<User> users = userService.list(new LambdaQueryWrapper<User>().in(User::getUserId,userIds));
            noticeDTO.setUserList(users);
            LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            //关联的邀请信息
            if("1".equals(notice.getNoticeType())){
                Invitation invitation = invitationService.getOne(new LambdaQueryWrapper<Invitation>().eq(Invitation::getNoticeId, noticeId).eq(Invitation::getInviteeId, loginUser.getUserId()));
                if(invitation==null){
                    noticeDTO.setInvitation(null);
                    noticeDTOS.add(noticeDTO);
                    continue;
                }
                InvitationDTO invitationDTO = new InvitationDTO();
                BeanUtil.copyProperties(invitation, invitationDTO);
                User inviter = userService.getById(invitation.getInviterId());
                User invitee = userService.getById(invitation.getInviteeId());
                invitationDTO.setInviterName(inviter.getUsername());
                invitationDTO.setInviteeName(invitee.getUsername());
                noticeDTO.setInvitation(invitationDTO);
            }
            noticeDTOS.add(noticeDTO);
        }
        return noticeDTOS;
    }

    @Override
    public PageBean<NoticeDTO> search(Map map) {
        Integer pageNum = (Integer) map.get("pageNum");
        Integer pageSize = (Integer) map.get("pageSize");

        // 获取嵌套的 search Map
        Map<String, Object> searchMap = (Map<String, Object>) map.get("search");
        //{pageNum=1, pageSize=10, search={username=, phone=, status=1, createTimeList=[2024-10-27T16:00:00.000Z, 2024-11-03T16:00:00.000Z], deptIdList=[1842128938393600002, 1842128590274756609]}}

        // 从 search Map 中获取值
        String pulishName = (String) searchMap.get("pulishName");
        String noticeType = (String) searchMap.get("noticeType");
        List<String> createTimeList = (List<String>) searchMap.get("createTimeList");
        List<String> tenantIdList = (List<String>) searchMap.get("tenantIdList");
        List<String> userIdList=new ArrayList<>();
        if(StringUtils.hasText(pulishName)){
            List<User> list = userService.list(new LambdaQueryWrapper<User>().like(User::getUsername, pulishName));
            userIdList = list.stream().map(User::getUserId).collect(Collectors.toList());
        }

        //把日期字符串转换为日期对象
        LocalDateTime startTime = null;
        LocalDateTime endTime = null;
        if (createTimeList != null && createTimeList.size() == 2) {
            //OffsetDateTime适用于解析带有 "Z" 的日期字符串。
            startTime = OffsetDateTime.parse(createTimeList.get(0), DateTimeFormatter.ISO_OFFSET_DATE_TIME).toLocalDateTime();
            endTime = OffsetDateTime.parse(createTimeList.get(1), DateTimeFormatter.ISO_OFFSET_DATE_TIME).toLocalDateTime();
        }
        LambdaQueryWrapper<Notice> queryWrapper = new LambdaQueryWrapper<>();
        //根据当前登录用户的权限查询
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<String> permissions = loginUser.getAuthorityStrings();
        if (!permissions.contains("ROLE_super")) {
            queryWrapper.eq(Notice::getTenantId, loginUser.getTenantId());
        }
        Page<Notice> page = new Page<>(pageNum, pageSize);


        queryWrapper.in(!userIdList.isEmpty(), Notice::getCreateId, userIdList)
                .in(tenantIdList != null && !tenantIdList.isEmpty(), Notice::getTenantId, tenantIdList)
                .eq(StringUtils.hasText(noticeType), Notice::getNoticeType, noticeType)
                .between(createTimeList != null && createTimeList.size() == 2, Notice::getCreateTime, startTime, endTime);
        Page<Notice> taskPage = this.page(page, queryWrapper);
        //将查询到的任务转换为DTO对象
        List<NoticeDTO> taskDTOList = getNoticeDTOS(taskPage.getRecords());
        //将查询到的任务列表封装到PageBean对象中
        PageBean<NoticeDTO> pageBean = new PageBean<>(taskPage.getCurrent(), taskPage.getSize(), taskPage.getTotal(), taskDTOList);
        return pageBean;
    }

    @Override
    public Result publish(NoticeDTO noticeDTO) {
        //根据当前登录用户的权限查询通知
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<String> permissions = loginUser.getAuthorityStrings();
        if (!permissions.contains("ROLE_super")&&!permissions.contains("ROLE_admin")) {
            return Result.error("无权限发布通知！");
        }

        String projectId = noticeDTO.getProjectId();
        List<ProjectUserRole> projectUserRoleList = projectUserRoleService.list(new LambdaQueryWrapper<ProjectUserRole>().eq(ProjectUserRole::getProjectId, projectId));
        Set<String> userIds = projectUserRoleList.stream().map(ProjectUserRole::getUserId).collect(Collectors.toSet());
        Notice notice = new Notice();
        BeanUtil.copyProperties(noticeDTO, notice);
        //转成list
        List<String> userIdsList = new ArrayList<>(userIds);

        //保存到notice表
        notice.setDelFlag("1");
        notice.setCreateTime(LocalDateTime.now());
        notice.setCreateId(loginUser.getUserId());
        this.save(notice);
        //保存到notice_user表
        List<NoticeUser> noticeUsers = new ArrayList<>();
        for (String userId : userIds) {
            NoticeUser noticeUser = new NoticeUser();
            noticeUser.setNoticeId(notice.getNoticeId());
            noticeUser.setUserId(userId);
            noticeUser.setStarFlag("0");
            noticeUser.setReadFlag("0");
            noticeUsers.add(noticeUser);
        }
        noticeUserService.saveBatch(noticeUsers);

        //发送通知
        ServerSentEventsManager.send(userIdsList, new ServerSentEventsResult<>(ServerSentEventsEnum.SSE_NOTICE, notice));
        return Result.success("发布成功");
    }

    @Override
    public Result delete(NoticeDTO noticeDTO) {
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if(!loginUser.getUserId().equals(noticeDTO.getCreateId())||!loginUser.getAuthorityStrings().contains("ROLE_super")){
            return Result.error("无权限删除!");
        }
        Notice notice = new Notice();
        BeanUtil.copyProperties(noticeDTO, notice);
        noticeUserService.remove(new LambdaQueryWrapper<NoticeUser>().eq(NoticeUser::getNoticeId, notice.getNoticeId()));
        return  Result.success(this.removeById(notice.getNoticeId()));
    }

    @Override
    public String sendProjectInviteNotice(List<String> noticeUserIds, Project project, Role role, LoginUser loginUser) {
        if(noticeUserIds.isEmpty()){
            return null;
        }
        Notice notice = new Notice();
        String noticeId = UUID.randomUUID().toString().replace("-", "");
        notice.setNoticeId(noticeId);
        notice.setNoticeTitle("项目" + project.getProjectName() + "的邀请通知");
        notice.setNoticeType("1");
        notice.setPriority("1");
        notice.setContent(loginUser.getUsername() + "邀请您成为项目" + project.getProjectName() + "的" + role.getRoleName());
        notice.setTenantId(project.getTenantId());
        notice.setProjectId(project.getProjectId());
        notice.setRoleId(role.getRoleId());
        notice.setDelFlag("1");
        notice.setCreateTime(LocalDateTime.now());
        notice.setCreateId(loginUser.getUserId());
        notice.setUpdateTime(LocalDateTime.now());
        notice.setUpdateId(loginUser.getUserId());
        this.save(notice);
        List<User> userList = userService.list(new LambdaQueryWrapper<User>().in(User::getUserId, noticeUserIds));
        //更新notice_user表
        for (User user : userList) {
            NoticeUser noticeUser = new NoticeUser();
            noticeUser.setNoticeId(notice.getNoticeId());
            noticeUser.setUserId(user.getUserId());
            noticeUser.setReadFlag("0");
            noticeUser.setStarFlag("0");
            noticeUserService.save(noticeUser);
        }
        //发送通知
        ServerSentEventsManager.send(noticeUserIds, new ServerSentEventsResult<>(ServerSentEventsEnum.SSE_NOTICE, notice));
        return noticeId;
    }

    @Override
    public void removeProjectInviteNotice(User user, Project project, Role role, LoginUser loginUser) {
        Notice notice = new Notice();
        notice.setNoticeId(UUID.randomUUID().toString().replace("-", ""));
        notice.setNoticeTitle("项目" + project.getProjectName() + "的移除通知");
        notice.setNoticeType("0");
        notice.setPriority("1");
        notice.setContent(loginUser.getUsername() + "已经将您移除项目" + project.getProjectName() + "的" + role.getRoleName() + "身份！");
        notice.setTenantId(project.getTenantId());
        notice.setProjectId(project.getProjectId());
        notice.setRoleId(role.getRoleId());
        notice.setDelFlag("1");
        notice.setCreateTime(LocalDateTime.now());
        notice.setCreateId(loginUser.getUserId());
        notice.setUpdateTime(LocalDateTime.now());
        notice.setUpdateId(loginUser.getUserId());
        this.save(notice);

        NoticeUser noticeUser = new NoticeUser();
        noticeUser.setNoticeId(notice.getNoticeId());
        noticeUser.setUserId(user.getUserId());
        noticeUser.setReadFlag("0");
        noticeUser.setStarFlag("0");
        noticeUserService.save(noticeUser);
        ServerSentEventsManager.send(user.getUserId(), new ServerSentEventsResult<>(ServerSentEventsEnum.SSE_NOTICE, notice));
    }

    @Override
    public void sendTaskInviteNotice(User user, Task task, Role role, LoginUser loginUser, Tenant tenant) {
        //更新notice表
        Notice notice = new Notice();
        notice.setNoticeId(UUID.randomUUID().toString().replace("-", ""));
        notice.setNoticeTitle("项目" + task.getProjectId() + "的 " + task.getTaskName() + " 任务分配通知");
        notice.setNoticeType("1");
        notice.setPriority("1");
        notice.setContent(loginUser.getUsername() + "邀请您成为项目" + task.getProjectId() + "的" + role.getRoleName());
        notice.setTenantId(tenant.getTenantId());
        notice.setProjectId(task.getProjectId());
        notice.setRoleId(role.getRoleId());
        notice.setDelFlag("1");
        notice.setCreateTime(LocalDateTime.now());
        notice.setCreateId(loginUser.getUserId());
        notice.setUpdateTime(LocalDateTime.now());
        notice.setUpdateId(loginUser.getUserId());
        this.save(notice);

        //更新notice_user表
        NoticeUser noticeUser = new NoticeUser();
        noticeUser.setNoticeId(notice.getNoticeId());
        noticeUser.setUserId(user.getUserId());
        noticeUser.setReadFlag("0");
        noticeUser.setStarFlag("0");
        noticeUserService.save(noticeUser);

        ServerSentEventsManager.send(user.getUserId(), new ServerSentEventsResult<>(ServerSentEventsEnum.SSE_NOTICE, notice));
    }

    @Override
    public void removeTaskInviteNotice(String userId, Task task, Project project, LoginUser loginUser) {
        //更新notice表
        Notice notice = new Notice();
        notice.setNoticeId(UUID.randomUUID().toString().replace("-", ""));
        notice.setNoticeTitle(task.getTaskName() + "任务取消通知");
        notice.setNoticeType("0");
        notice.setPriority("2");
        notice.setContent(loginUser.getUsername() + "将已将您在项目" + task.getProjectId() + "中的" + task.getTaskName() + "任务取消,请知悉！");
        Tenant tenant = tenantService.getById(project.getTenantId());
        notice.setTenantId(tenant.getTenantId());
        notice.setProjectId(task.getProjectId());
        notice.setDelFlag("1");
        notice.setCreateTime(LocalDateTime.now());
        notice.setCreateId(loginUser.getUserId());
        notice.setUpdateTime(LocalDateTime.now());
        notice.setUpdateId(loginUser.getUserId());
        this.save(notice);

        User user = userService.getById(userId);
        NoticeUser noticeUser = new NoticeUser();
        noticeUser.setNoticeId(notice.getNoticeId());
        noticeUser.setUserId(user.getUserId());
        noticeUser.setReadFlag("0");
        noticeUser.setStarFlag("0");
        noticeUserService.save(noticeUser);

        ServerSentEventsManager.send(userId, new ServerSentEventsResult<>(ServerSentEventsEnum.SSE_NOTICE, notice));

    }

    @Override
    public void taskDeleteNotice(Task task, Project project, List<TaskUser> taskUserList, LoginUser loginUser) {
        //更新notice表
        Notice notice = new Notice();
        notice.setNoticeId(UUID.randomUUID().toString().replace("-", ""));
        notice.setNoticeTitle(task.getTaskName() + "任务删除通知");
        notice.setNoticeType("0");
        notice.setPriority("2");
        notice.setContent(loginUser.getUsername() + "将项目" + task.getProjectId() + "的" + task.getTaskName() + "任务删除,请知悉！");
        Tenant tenant = tenantService.getById(project.getTenantId());
        notice.setTenantId(tenant.getTenantId());
        notice.setProjectId(task.getProjectId());
        notice.setDelFlag("1");
        notice.setCreateTime(LocalDateTime.now());
        notice.setCreateId(loginUser.getUserId());
        notice.setUpdateTime(LocalDateTime.now());
        notice.setUpdateId(loginUser.getUserId());
        this.save(notice);

        //更新notice_user表
        for (TaskUser taskUser : taskUserList) {
            User user = userService.getById(taskUser.getUserId());
            NoticeUser noticeUser = new NoticeUser();
            noticeUser.setNoticeId(notice.getNoticeId());
            noticeUser.setUserId(user.getUserId());
            noticeUser.setReadFlag("0");
            noticeUser.setStarFlag("0");
            noticeUserService.save(noticeUser);
        }

        List<String> userIdsList = taskUserList.stream().map(TaskUser::getUserId).collect(Collectors.toList());
        ServerSentEventsManager.send(userIdsList, new ServerSentEventsResult<>(ServerSentEventsEnum.SSE_NOTICE, notice));
    }
}
